﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.ProgressBar;
using YJKOpeningCommon.DataEnum;
using YJKOpeningCommon.DbOpening;
using YJKOpeningCommon.OpeningProfile;
using YJKOpeningCommon.Public;
using YJKOpeningDesignInput.Public;

namespace YJKOpeningDesignInput.Composite
{
	public class CompositeHandle
	{
		public CompositeHandle(UIDocument uiDoc)
		{
			this.m_uiDoc = uiDoc;
			this.mepData = new MEPData();
			this.GetGrids();
		}

		private void GetGrids()
		{
			new List<Document>();
			List<Document> linkDocs = CommonInterface.GetLinkDocs(this.m_uiDoc.Document);
			linkDocs.Add(this.m_uiDoc.Document);
			GridData.GetGridInfos(linkDocs, ref this.mepData.m_lstInfos);
		}

		public void CompositeDbOpening(ref LinkedList<DbOpeningBase> lstOpening, ref bool isComposite)
		{
			ProgressBarForm progressBarForm = new ProgressBarForm(lstOpening.Count, ProgressBarStyle.Blocks, true);
			progressBarForm.Show();
			progressBarForm.ShowInTaskbar = false;
			progressBarForm.Text = "合并洞口";
			LinkedList<DbOpeningBase> linkedList = new LinkedList<DbOpeningBase>();
			LinkedList<DbOpeningBase> linkedList2 = new LinkedList<DbOpeningBase>();
			LinkedList<DbOpeningBase> linkedList3 = new LinkedList<DbOpeningBase>();
			bool flag = false;
			IEnumerator enumerator = lstOpening.GetEnumerator();
			int num = 0;
			while (enumerator.MoveNext())
			{
				bool flag2 = false;
				num++;
				DbOpeningBase dbOpeningBase = enumerator.Current as DbOpeningBase;
				if (dbOpeningBase.m_profile is OpeningProfileEquipRect || dbOpeningBase is DbRectBeamOpening)
				{
					if (!CompositeHandle.HavingThisOpening(linkedList2, dbOpeningBase))
					{
						linkedList2.AddLast(dbOpeningBase);
					}
					progressBarForm.RefreshProgressBar();
				}
				else if (CompositeHandle.HavingThisOpening(linkedList, dbOpeningBase))
				{
					progressBarForm.RefreshProgressBar();
				}
				else
				{
					LinkedListNode<DbOpeningBase> linkedListNode = lstOpening.Find(dbOpeningBase);
					linkedListNode = linkedListNode.Next;
					while (linkedListNode != null)
					{
						DbOpeningBase value = linkedListNode.Value;
						bool flag3 = false;
						if (!(value is DbCompositeOpening) && CompositeHandle.HavingThisOpening(linkedList, value))
						{
							linkedListNode = linkedListNode.Next;
						}
						else if (value.m_profile is OpeningProfileEquipRect || value is DbRectBeamOpening)
						{
							if (!CompositeHandle.HavingThisOpening(linkedList2, value))
							{
								linkedList2.AddLast(value);
							}
							linkedListNode = linkedListNode.Next;
						}
						else
						{
							if (this.IsCompositable(dbOpeningBase, value))
							{
								flag2 = true;
								flag3 = true;
								flag = true;
								DbCompositeOpening dbCompositeOpening = null;
								if (this.DoCompositeDbOpening(dbOpeningBase, value, ref dbCompositeOpening) && dbCompositeOpening != null)
								{
									isComposite = true;
									linkedList.AddLast(dbCompositeOpening);
									linkedList3.AddLast(dbCompositeOpening);
									CompositeHandle.AddCompositeOpening(dbOpeningBase, ref linkedList3);
									CompositeHandle.AddCompositeOpening(value, ref linkedList3);
									break;
								}
							}
							if (!flag3 && !CompositeHandle.HavingThisOpening(linkedList2, value))
							{
								linkedList2.AddLast(value);
							}
							linkedListNode = linkedListNode.Next;
						}
					}
					if (!flag2 && !CompositeHandle.HavingThisOpening(linkedList2, dbOpeningBase))
					{
						linkedList2.AddLast(dbOpeningBase);
					}
				}
			}
			foreach (DbOpeningBase dbOpeningBase2 in linkedList2)
			{
				if (!CompositeHandle.HavingThisOpening(linkedList3, dbOpeningBase2))
				{
					linkedList.AddLast(dbOpeningBase2);
				}
			}
			if (flag)
			{
				progressBarForm.Dispose();
				this.CompositeDbOpening(ref linkedList, ref isComposite);
			}
			lstOpening = linkedList;
			progressBarForm.Dispose();
		}

		private static void AddCompositeOpening(DbOpeningBase opening, ref LinkedList<DbOpeningBase> lstOpening)
		{
			if (opening is DbCompositeOpening)
			{
				lstOpening.AddLast(opening);
			}
		}

		private bool IsCompositable(DbOpeningBase op1, DbOpeningBase op2)
		{
			if (op1 == null || op2 == null)
			{
				return false;
			}
			if (op1.m_profile.m_dExtendDist == 50.0 || op2.m_profile.m_dExtendDist == 50.0 || op1.m_profile.m_dTolerance == 300.0 || op1.m_profile.m_dTolerance == 300.0)
			{
			}
			if (op1.m_strHostUniqueId != op2.m_strHostUniqueId)
			{
				return false;
			}
			List<XYZ> lstPt = new List<XYZ>();
			List<XYZ> lstPt2 = new List<XYZ>();
			XYZ projectPt = this.GetProjectPt(op1, op2);
			Transform transform = null;
			op1.GetProfileOutLine3D(ref lstPt, ref transform, true, null);
			op2.GetProfileOutLine3D(ref lstPt2, ref transform, true, projectPt);
			return Interface.IsIntersect(lstPt, lstPt2);
		}

		private XYZ GetProjectPt(DbOpeningBase op1, DbOpeningBase op2)
		{
			XYZ result = null;
			if (op1.m_eHostObject == EHostObject.eArchWall || op1.m_eHostObject == EHostObject.eStruWall)
			{
				XYZ directionProfile = op1.m_profile.m_directionProfile;
				result = (this.GetMirPt(directionProfile, op1.m_profile.m_position, op2.m_profile.m_position) + op2.m_profile.m_position) / 2.0;
			}
			return result;
		}

		private XYZ GetMirPt(XYZ normal, XYZ pt1, XYZ pt2)
		{
			Transaction transaction = new Transaction(this.m_uiDoc.Document, "GetMirrorPt");
			XYZ result;
			try
			{
				transaction.Start();
				XYZ xyz = Transform.CreateReflection(RevitVersionFuncs.CreatePlanByNormalAndOrigin(normal, pt1)).OfPoint(pt2);
				transaction.Commit();
				result = xyz;
			}
			catch (Exception)
			{
				transaction.RollBack();
				throw;
			}
			return result;
		}

		private bool DoCompositeDbOpening(DbOpeningBase op1, DbOpeningBase op2, ref DbCompositeOpening compositeOpening)
		{
			Document document = this.m_uiDoc.Document;
			if (op1 == null || op2 == null)
			{
				return false;
			}
			if (op1.m_strGuid == op2.m_strGuid)
			{
				return false;
			}
			List<DbOpeningBase> list = new List<DbOpeningBase>();
			List<DbOpeningBase> collection = new List<DbOpeningBase>();
			CompositeHandle.AddOpening2Lst(ref list, op1);
			CompositeHandle.AddOpening2Lst(ref collection, op2);
			list.AddRange(collection);
			if (op1.m_eHostObject == EHostObject.eArchWall || op1.m_eHostObject == EHostObject.eStruWall)
			{
				compositeOpening = new DbCompositeRectWallOpening();
			}
			else if (op1.m_eHostObject == EHostObject.eArchFloor || op1.m_eHostObject == EHostObject.eStruFloor)
			{
				compositeOpening = new DbCompositeRectFloorOpening();
			}
			this.SetCompositeOpeningAttribute(ref compositeOpening, op1);
			List<XYZ> list2 = new List<XYZ>();
			List<XYZ> collection2 = new List<XYZ>();
			Transform transform = null;
			op1.GetProfileOutLine3D(ref list2, ref transform, false, null);
			XYZ projectPt = this.GetProjectPt(op1, op2);
			op2.GetProfileOutLine3D(ref collection2, ref transform, false, projectPt);
			list2.AddRange(collection2);
			compositeOpening.m_profile.m_directionCutObj = XYZ.BasisZ;
			compositeOpening.GetCompositeOpeningData(list2, document);
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			if (Interface.GetXmlData(ref dictionary))
			{
				compositeOpening.m_profile.m_dExtendDist = AssistFunc.mmToFeet(Convert.ToDouble(dictionary["CompositeOutSize"]));
			}
			else
			{
				compositeOpening.m_profile.m_dExtendDist = AssistFunc.mmToFeet(50.0);
			}
			this.SetOpeningDataGrid(ref compositeOpening, document);
			Interface.DeleteModelGroup(document, op1.m_idModelGroup);
			Interface.DeleteModelGroup(document, op2.m_idModelGroup);
			GraphicsStyle graphicsStyle = null;
			CommonInterface.GetPreViewStyle(ref graphicsStyle, document);
			if (graphicsStyle != null)
			{
				PreViewScene preViewScene = new PreViewScene(document, graphicsStyle.Id, 0.32808398950131235);
				Element element = null;
				compositeOpening.CreateOpeningPreviewInstance(out element, preViewScene);
				if (element != null)
				{
					compositeOpening.m_idModelGroup = element.Id;
				}
			}
			compositeOpening.m_lstDbFamilyOpening = list;
			return true;
		}

		private void SetCompositeOpeningAttribute(ref DbCompositeOpening compositeOpening, DbOpeningBase opening)
		{
			compositeOpening.m_eHostObject = opening.m_eHostObject;
			compositeOpening.m_eCutObject = ECutObject.eMulti;
			compositeOpening.m_eSpeciality = ESpeciality.eMulti;
			compositeOpening.m_strHostUniqueId = opening.m_strHostUniqueId;
			compositeOpening.m_strCutUniqueId = string.Empty;
			compositeOpening.m_dHostWidth = opening.m_dHostWidth;
			compositeOpening.m_strFloorPlan = opening.m_strFloorPlan;
			compositeOpening.m_strGuid = Guid.NewGuid().ToString();
			OpeningProfileRect profile = new OpeningProfileRect();
			compositeOpening.m_profile = profile;
			compositeOpening.m_profile.m_dTolerance = opening.m_profile.m_dTolerance;
		}

		private static bool HavingThisOpening(LinkedList<DbOpeningBase> lstOpening, DbOpeningBase opening)
		{
			if (opening is DbCompositeOpening)
			{
				foreach (DbOpeningBase dbOpeningBase in lstOpening)
				{
					if (opening.m_strGuid == dbOpeningBase.m_strGuid)
					{
						return true;
					}
				}
				return false;
			}
			foreach (DbOpeningBase dbOpeningBase2 in lstOpening)
			{
				if (dbOpeningBase2 is DbCompositeOpening)
				{
					using (List<DbOpeningBase>.Enumerator enumerator2 = (dbOpeningBase2 as DbCompositeOpening).m_lstDbFamilyOpening.GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							if (enumerator2.Current.m_strGuid.Equals(opening.m_strGuid))
							{
								return true;
							}
						}
						continue;
					}
				}
				if (opening.m_strGuid.Equals(dbOpeningBase2.m_strGuid))
				{
					return true;
				}
			}
			return false;
		}

		private void SetOpeningDataGrid(ref DbCompositeOpening opening, Autodesk.Revit.DB.Document doc)
		{
			if (this.mepData.m_lstInfos != null && this.mepData.m_lstInfos.Count != 0)
			{
				Interface.GetXYGrid(opening.m_profile.m_position, this.mepData.m_lstInfos, ref opening.m_strAxisX, ref opening.m_strAxisY);
				return;
			}
			opening.m_strAxisX = string.Empty;
			opening.m_strAxisY = string.Empty;
		}

		private static void AddOpening2Lst(ref List<DbOpeningBase> lstOpening, DbOpeningBase opening)
		{
			if (opening.m_profile is OpeningProfileRect)
			{
				DbCompositeOpening dbCompositeOpening = opening as DbCompositeOpening;
				if (dbCompositeOpening != null && dbCompositeOpening.m_lstDbFamilyOpening.Count != 0)
				{
					for (int i = 0; i < dbCompositeOpening.m_lstDbFamilyOpening.Count; i++)
					{
						DbOpeningBase item = dbCompositeOpening.m_lstDbFamilyOpening[i];
						lstOpening.Add(item);
					}
					return;
				}
				if (opening is DbRectBeamOpening || opening is DbRectFloorOpening || opening is DbRectWallOpening)
				{
					lstOpening.Add(opening);
					return;
				}
			}
			else if (opening.m_profile is OpeningProfileCircle)
			{
				lstOpening.Add(opening);
			}
		}

		private UIDocument m_uiDoc;

		private MEPData mepData;
	}
}
